package Game;

import java.awt.Image;
import java.util.LinkedList;
import java.util.Iterator;
import java.io.Serializable;

import graphics.Sprite;
import graphics.Animation;

/**
    The TileMap class contains the data for a tile-based
    map, including Sprites. Each tile is a reference to an
    Image. Of course, Images are used multiple times in the tile
    map.
*/
public class TileMap implements Serializable{

    //private Image[][] tiles;

    public static int colouredTiles=0;
    private int totalTiles;
    
    //double array of Tile objects
    private Tile[][] tiles;

    private LinkedList sprites;
    private Sprite player;

    private Image background;
    boolean playBGAnim,backColoured,fullyColoured;
    private Animation backGAnim,backRevGAnim,backgroundAnim;
    private Image backgroundC;
    private Image backgroundGS;

    /**
        Creates a new TileMap with the specified width and
        height (in number of tiles) of the map.
    */
    public TileMap(int width, int height) {
        tiles = new Tile[width][height];
        //tiles = new Image[width][height];
        sprites = new LinkedList();
        playBGAnim=false;
        backColoured=false;
        fullyColoured=false;
        totalTiles=0;
        colouredTiles=0;
    }
    
    public void initialize(Animation forward,Animation backward){
        backGAnim=forward;
        backRevGAnim=backward;
        backgroundAnim=backGAnim;
        background=backgroundAnim.getImage();
    }
    
    public void setBackgroundColoured(boolean coloured){
        if(coloured){
            backgroundAnim=backGAnim;
        }else{
            backgroundAnim=backRevGAnim;
        }
        playBGAnim=true;
    }

    public Image getBackground() {
        return background;
    }

    public void setBackground(Image background) {
        this.background = background;
    }

    public Image getBackgroundC() {
        return backgroundC;
    }

    public void setBackgroundC(Image backgroundC) {
        this.backgroundC = backgroundC;
    }

    public Image getBackgroundGS() {
        return backgroundGS;
    }

    public void setBackgroundGS(Image backgroundGS) {
        this.backgroundGS = backgroundGS;
    }




    /**
        Gets the width of this TileMap (number of tiles across).
    */
    public int getWidth() {
        return tiles.length;
    }


    /**
        Gets the height of this TileMap (number of tiles down).
    */
    public int getHeight() {
        return tiles[0].length;
    }


    /**
        Gets the tile at the specified location. Returns null if
        no tile is at the location or if the location is out of
        bounds.
    */
    public Tile getTile(int x, int y) {
        if (x < 0 || x >= getWidth() ||
            y < 0 || y >= getHeight())
        {
            return null;
        }
        else {
            return tiles[x][y];
        }
    }

    /*public Tile getTile(int x, int y) {
        //handle circular stuff
        if(x < 0){
            int temp=x%getWidth();
            if(temp!=0)
                x=getWidth()+temp;
            else
                x=0;
        }
        if(x>=getWidth()){
            x=x%getWidth();
        }
        

        //if (x < 0 || x >= getWidth() ||
            if(y < 0 || y >= getHeight())
        {
            return null;
        }
        else {
            return tiles[x][y];
        }
    }*/


    /**
        Sets the tile at the specified location.
    */
    /*public void setTile(int x, int y, Image tile) {
        tiles[x][y] = tile;
    }*/
    public void setTile(int x, int y, Tile tile) {
        totalTiles++;
        tiles[x][y] = tile;
    }


    /**
        Gets the player Sprite.
    */
    public Sprite getPlayer() {
        return player;
    }


    /**
        Sets the player Sprite.
    */
    public void setPlayer(Sprite player) {
        this.player = player;
    }


    /**
        Adds a Sprite object to this map.
    */
    public void addSprite(Sprite sprite) {
        sprites.add(sprite);
    }


    /**
        Removes a Sprite object from this map.
    */
    public void removeSprite(Sprite sprite) {
        sprites.remove(sprite);
    }


    /**
        Gets an Iterator of all the Sprites in this map,
        excluding the player Sprite.
    */
    public Iterator getSprites() {
        return sprites.iterator();
    }
    /**
     * Checks whether all the tiles in the map are coloured
     * @return whether all the tiles are coloured or not
     */
    public boolean checkFullyColored(){
        boolean fullyColored=true;

        for(int x=0;x<getWidth();x++){
            for(int y=0;y<getHeight();y++){
                if(tiles[x][y]!=null){
                    if(!tiles[x][y].isColored()){
                        fullyColored=false;
                    }
                }
            }
        }
        /*System.out.println("total tiles: "+totalTiles);
        System.out.println("coloured tiles: "+colouredTiles);
        if(colouredTiles>=totalTiles)
            return true;
        else
            return false;*/
        return fullyColored;
    }
    /**
     * Checks whether the tile at that location is collidable
     *
     * @param x
     * @param y
     * @return
     */
    public boolean isCollisionTile(int x,int y){
        if((/*x>=0&&x<getWidth())&&*/(y>=0&&y<getHeight()))){
            //if(tiles[x][y]!=null){
            if(getTile(x,y)!=null){
                if(getTile(x,y).isCollidable())
                    return true;
            }
        }
        return false;
    }
    
    public void update(long elapsedTime){
        for(int x=0;x<getWidth();x++){
            for(int y=0;y<getHeight();y++){
                if(tiles[x][y]!=null)
                    tiles[x][y].update(elapsedTime);
            }
        }
        boolean temp=checkFullyColored();
        System.out.println("temp: "+temp);
        System.out.println("fully: "+fullyColoured);
        if(temp!=fullyColoured){
            fullyColoured=temp;
            if(temp){
                backgroundAnim=backGAnim;
                
            }else{
                backgroundAnim=backRevGAnim;
            }
            playBGAnim=true;
            backgroundAnim.start();
        }
        
        if(playBGAnim){
            System.out.println("Got here!!!!");
            backgroundAnim.update(elapsedTime);
            background=backgroundAnim.getImage();
        }
    }

}
